package cn.edu.scau.cmi.crawler.service;

import java.util.Calendar;
import java.util.HashSet;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import cn.edu.scau.cmi.ema.controller.base.CmiEmaController;
import cn.edu.scau.cmi.ema.domain.*;
import cn.edu.scau.cmi.ema.service.base.EntityFactoryService;
import cn.edu.scau.cmi.ema.util.CmiSetUtil;
import cn.edu.scau.cmi.ema.util.CmiTimeUtil;
import cn.edu.scau.cmi.front.dao.CmiFoodDAO;

@Service
public class LidanEventImportServiceImpl extends CmiEmaController implements LidanEventImportService{
	
	@Autowired EntityFactoryService entityFactory;
	@Autowired CmiFoodDAO cmiFoodDAO;
	
	@Override
	public boolean importEvent(Event9ld event9ld) {
//	为了提高效率，没有food的事件不保存，免得初始化event浪费时间
		
//		（0）通过食物的名称-》生产商 | 已有的事件的来源地址确定食物，
//		如果找到了已有的食物记录，就返回这个食物，
//		如果没有，就新建一个持久化的食物记录。
		Food food = buildFood(event9ld);
		if(food == null) {
			System.out.println("Event的Food是空，该数据没有意义");
			event9ld.setImported(false);//没有导入
			event9ldService.saveEvent9ld(event9ld);
			return false;
		}
		
		Foodtype foodtype = buildFoodtype(event9ld);
		food.setFoodtype(foodtype);
		food = foodDAO.store(food);
		foodDAO.flush();
		
//		（1）初始化一个event对象
		Event event = entityFactory.initEvent();
		
//		（2）设置默认基本属性：
		event.setAuditTime(Calendar.getInstance());
		
//		（3）设置基本属性：
		
		event.setName(event9ld.getName());
		event.setDescription(event9ld.getDescription());
		
		String[] discoveryTimes = event9ld.getDiscoverytime().split("/");//.replace('/', '-');
		String discoveryTimeString = discoveryTimes[2] + "-" + discoveryTimes[1] + "-" + discoveryTimes[0];
		event.setDiscoveryTime(CmiTimeUtil.getYMDCalendar(discoveryTimeString));
//		（4）设置直接外键
//		李丹的事件没有主体，初始化envet的时候已经设置了这个值。
		
//		Subject subject = subjectDAO.findSubjectById(-2);
//		event.setSubject(subject);
//		
		User auditor = CmiSetUtil.getFirstInstance(userDAO.findUserByName("李丹"));
		event.setAuditor(auditor);
		
		User reportor = buildReportor(event9ld);
		event.setReportor(reportor);

		Url url = buildUrl(event9ld);
		event.setUrl(url);
		
		Address discoveryAddress = buildDiscoveryAddress(event9ld);
		event.setDiscoveryAddress(discoveryAddress);
		
		Address sourceAddress = buildSourceAddress(event9ld);
		event.setSourceAddress(sourceAddress);

//		掺假类型，多对多，
		Set<Adultertype> adultertypes = buildAdultertype(event9ld);
		event.setAdultertypesForEvent(adultertypes);
		
		Set<Foodbatchfiller> foodbatchfillers = buildFoodbatchfiller(event9ld);
		
		Foodbatch foodbatch = entityFactory.initFoodbatch();
		foodbatch.setFood(food);
		foodbatch.setDetectmethod(detectmethodDAO.findDetectmethodById(-2));
		foodbatch.setUnit(unitDAO.findUnitById(-2));
		foodbatch.setFoodbatchfillersForFoodbatch(foodbatchfillers);
//		TODO !!!!!!日期需要修改，暂时使用当前的值
		Calendar date = Calendar.getInstance();
		foodbatch.setDate(date );
		foodbatch.setName(event.getSubject().getName() + event.getName() + "的食物批次");
		foodbatch = foodbatchService.saveFoodbatch(foodbatch);

		event.setFoodbatch(foodbatch);
		
		event = eventService.saveEvent(event);
		
//		第三部分：事件save后，保存引用事件的数据，
		
		Punish punish = buildPunish(event9ld);
		Eventpunish eventpunish = buildEventpunish(event9ld);
		eventpunish.setDate(Calendar.getInstance());
		Set<Eventpunish> eventpunishs = new HashSet<Eventpunish>();
		if(eventpunish != null) {
			eventpunish.setPunish(punish);
			eventpunish.setEvent(event);
			eventpunish = eventpunishService.saveEventpunish(eventpunish);
			eventpunishs.add(eventpunish);
		}
		event.setEventpunishsForEvent(eventpunishs);
		
//		好像应该先保存event，才能保存eventadulterlink
		Adulterlink adulterlink = buildAdulterlink(event9ld);
//		Set<Eventadulterlink> eventadulterlinks = new HashSet<Eventadulterlink>();
		
		Eventadulterlink eventadulterlink = entityFactory.initEventadulterlink();
		eventadulterlink.setEvent(event);
		eventadulterlink.setAdulterlink(adulterlink);
		eventadulterlink = eventadulterlinkService.saveEventadulterlink(eventadulterlink);
//		
		Hazard hazard = buildHazard(event9ld);
		Set<Eventhazard> hazards = new HashSet<Eventhazard>();
		if(hazard !=null) {
			Eventhazard eventhazard= entityFactory.iniEventhazard();
			eventhazard.setEvent(event);
			eventhazard.setHazard(hazard);
			hazards.add(eventhazard);
			event.setEventhazardsForEvent(hazards);
		}
		eventDAO.store(event);
		
//		eventadulterlinks.add(eventadulterlink);
//		event.setEventadulterlinksForEvent(eventadulterlinks);
		
//		删除已经导入的数据
		event9ldService.deleteEvent9ld(event9ld);
		return true;
	}
	
	private Hazard buildHazard(Event9ld event9ld) {
		Hazard hazard = null;
		String hazardString = event9ld.getHazard();
		if(hazardString ==null || hazardString.trim().equals("")) {
			return hazard;
		}
//		风险也不能自己增加，预定义
		Set<Hazard> hazards = hazardDAO.findHazardByName(hazardString);
		if(hazards.size()>0) {
			hazard = CmiSetUtil.getFirstInstance(hazards);
		}else {
			hazard = hazardDAO.findHazardById(-2);
		}
		return hazard;
	}

	//	欺诈环节也不能新增。
	private Adulterlink buildAdulterlink(Event9ld event9ld) {
		Adulterlink adulterlink = null;
		String adulterlinkString = event9ld.getAdulterlink();
		if(adulterlinkString == null || adulterlinkString.trim().equals("")) {
			return adulterlink;
		}
		
		Set<Adulterlink> adulterlinks = adulterlinkDAO.findAdulterlinkByName(adulterlinkString);
		if(adulterlinks.size()>0) {
			adulterlink = CmiSetUtil.getFirstInstance(adulterlinks);
		}else {
			adulterlink = adulterlinkDAO.findAdulterlinkById(-2);
		}
		return adulterlink;
	}

	private User buildReportor(Event9ld event9ld) {
		User user = null;
		String sourceString = event9ld.getSource();
		
		if(sourceString == null || sourceString.trim().equals("")) {
			return user;
		}

		Set<User> users = userDAO.findUserByName(event9ld.getSource());
		if(users.size()>0) {
			user = CmiSetUtil.getLastInstance(users);
		}else {
			user = entityFactory.initUser();
			user.setName(sourceString);
			user.setUsername(sourceString);
			user.setPassword("；卡事件的发生和发士大夫");
			user = userService.saveUser(user);
		}
		return user;
	}

	//	如果能获取处罚，不添加了。这个是类型。
	private Punish buildPunish(Event9ld event9zwz) {
		Punish punish = punishDAO.findPunishById(-2);
		String punishString = event9zwz.getEffect();
		
		if(punishString ==null) {
			return punish;
		}
		
		Set<Punish> punishs = punishDAO.findPunishByName(punishString);
		
		if(punishs.size() > 0) {
			punish = CmiSetUtil.getLastInstance(punishs);
		}

		return punish;
	}







//	如果环节名称是空，返回id是-2的数据，如果没有找到就新建一个数据
	private Discoverylink buildDiscoverylink(Event9zwz event9zwz) {
		Discoverylink discoverylink = entityFactory.initDiscoverylink();
		
		String discoverylinkString = event9zwz.getDiscoverylink();
		if (discoverylinkString == null) {
			return discoverylinkDAO.findDiscoverylinkById(-2); 
		}
		
		Set<Discoverylink> discoverylinks = discoverylinkDAO.findDiscoverylinkByName(event9zwz.getDiscoverylink());
		if(discoverylinks.size() > 0) {
			discoverylink = CmiSetUtil.getLastInstance(discoverylinks);
		}else {
			discoverylink.setName(event9zwz.getDiscoverylink());
			discoverylink = discoverylinkService.saveDiscoverylink(discoverylink);
		}
		return discoverylink;
	}

//	填充物需要查找，查找不到的就要保持
	private Set<Foodbatchfiller> buildFoodbatchfiller(Event9ld event9zwz) {
		Set<Foodbatchfiller> foodbatchfillers = new HashSet<Foodbatchfiller>();
		
		String foodbatcherfillerString = event9zwz.getFoodbatchfiller();
		if(foodbatcherfillerString == null) {
			return null;
		}
		
		String[] foodbatcherfillerStrings = foodbatcherfillerString.split("；");
		for(int i = 0; i< foodbatcherfillerStrings.length; i++) {
			Set<Foodbatchfiller> fs = foodbatchfillerDAO.findFoodbatchfillerByName(foodbatcherfillerStrings[i]);
//			通过名字查找，如果查找到了添加加到里面来；
			if(fs.size()>0) {
				foodbatchfillers.addAll(foodbatchfillers);
//				通过名字查找，没有查找到了，新建这条记录，并添加加到里面来；
			}else {
				Foodbatchfiller ff = entityFactory.initFoodbatchfiller();
				ff.setName(foodbatcherfillerStrings[i]);
				ff = foodbatchfillerService.saveFoodbatchfiller(ff);
				foodbatchfillers.add(ff);
			}
		}
		return foodbatchfillers;
	}

	private Set<Adultertype> buildAdultertype(Event9ld event9zwz) {
		Set<Adultertype> adultertypes = new HashSet<Adultertype>();
		
		String[] adultertypeNames = event9zwz.getAdultertype().split("；");
		for(int i =0; i<adultertypeNames.length;i++) {
			Set<Adultertype> s = adultertypeDAO.findAdultertypeByName(adultertypeNames[i]);
			adultertypes.addAll(s);
		}
		
		if(adultertypes.size() <1) {
			adultertypes.add(adultertypeDAO.findAdultertypeById(-2));
		}
		
		return adultertypes;
	}

	private Eventpunish buildEventpunish(Event9ld event9zwz) {
		Eventpunish eventpunish = entityFactory.initEventpunish();
		eventpunish.setName(event9zwz.getEffect());
		return eventpunish;
	}

//	李丹的数据的URL是内部数据，不能公开
	private Url buildUrl(Event9ld event9ld) {
		Url url = null;
		String urlString = event9ld.getUrl();
		if(urlString ==null || urlString.trim().equals("")) {
			return url;
		}
		
		Set<Url> urls = urlDAO.findUrlByName(urlString);
		if(urls.size()>0) {
			url = CmiSetUtil.getFirstInstance(urls);
		}else {
			url = entityFactory.initUri();
			url.setValue("内部文件，不对外展示，文件编号：" + urlString);
			url.setName("内部文件，文件编号：" + urlString);
			url = urlService.saveUrl(url);
		}
		return url;
	}

	private Address buildDiscoveryAddress(Event9ld event9zwz) {
//		有省、市、县地址，先找县，再找市，再找省
		Set<Address> discoveryAddresss = addressDAO.findAddressByName(event9zwz.getDiscoveraddress());
		if(discoveryAddresss.size()>0) {
			return CmiSetUtil.getLastInstance(discoveryAddresss);
		}
		
		return addressDAO.findAddressById(-2);
	}
	
	private Address buildSourceAddress(Event9ld event9zwz) {
//		有省、市、县地址，先找县，再找市，再找省
		Set<Address> countyAddresss = addressDAO.findAddressByName(event9zwz.getSourceaddress());
		if(countyAddresss.size()>0) {
			return CmiSetUtil.getLastInstance(countyAddresss);
		}
		return addressDAO.findAddressById(-2);
	}
	
	private Detect buildDetect(Event9ld crawlerevent) {
		Detect detect = entityFactory.initDetect();
		return detect;
	}

	private Detectdetail buildDetectdetail(Event9ld enent9zwz) {
		Detectdetail instance = entityFactory.initDetectdetail();//CmiSetUtil.getSoleInstance(detectdetailDAO.findDetectdetailByName(enent9zwz.getDetectdetail()));
		return instance;
	}


//	没有食物批次，对每一个事件创建一个只适用于链接的食物。食物批次添加一个是否真实的食物批次。
	private Foodbatch buildFoodbatch(Event9ld enent9zwz) {
		Foodbatch foodbatch = entityFactory.initFoodbatch();
		return foodbatch;
	}

	private Food buildFood(Event9ld event9xls) {
		
		String foodName = event9xls.getFood();
		if(foodName == null || foodName.trim().equals("")) {
			return null;
		}
//		Food food = entityFactory.initFood();
		Set<Food> foodsByName = new HashSet<Food>();
		
		String producerName = event9xls.getProducer();
		
//		生产商：如果excel中不存在，
		Producer producer = null;
		if(!( producerName == null || producerName.trim().equals(""))) {
//			生产商名称唯一
			Set<Producer> producers = producerDAO.findProducerByName(event9xls.getProducer());
			if(producers.size()>0) {
				producer = CmiSetUtil.getFirstInstance(producers);			
				
				Set<Food> fs = cmiFoodDAO.findFoodsByNameAndProducer(foodName, producer.getName());
				if(fs.size()>0) {
					return CmiSetUtil.getFirstInstance(fs);
				}
				Food food = entityFactory.initFood();
				food.setName(foodName);
				food.setProducer(producer);
				food = foodService.saveFood(food);
				return food;
			}else {
				producer = entityFactory.initProducer();
				producer.setName(producerName);
				producer = producerService.saveProducer(producer);
				
				Food food = entityFactory.initFood();
				food.setName(foodName);
				food.setProducer(producer);
				food = foodService.saveFood(food);
				return food;
			}
		}else {
			foodsByName = foodDAO.findFoodByName(foodName);
			if(foodsByName.size()==0) {
				Food food = entityFactory.initFood();
				food.setName(foodName);
				food = foodService.saveFood(food);
				return food;
			}			
			
			for (Food foodByName : foodsByName) {
//				估计是懒加载的原有，不能获取本次导入请求过程中添加的foodbatch，因此，通过foodbatchDAO的方式获取
//				Set<Foodbatch> foodbatchs = foodByName.getFoodbatchsForFood();
				Set<Foodbatch> foodbatchs = foodbatchDAO.findFoodbatchsByFood(foodByName.getId(), -1, -1);
				
				for (Foodbatch foodbatch : foodbatchs) {
//					每个食物批次有多个事件
//					Set<Event> events = foodbatch.getEventsForFoodbatch();
					Set<Event> events = eventDAO.findEventsByFoodbatch(foodbatch.getId(), -1, -1);
					
					for (Event event : events) {
//						每个事件地址。事件来源地址为空，保持到数据库中是-2；
//						TODO 待解决，纯净水没有厂商、来源地、发现地导致多个food的记录缺陷原因：
//						因为数据库中没有地址用的id为-2的地址代替，而电子表格中是空字符串
						
						String eventsourceaddressName = event.getSourceAddress().getName();
						String eventdiscoveryaddressName = event.getDiscoveryAddress().getName();
						String event9xlsDiscoveryAddress = event9xls.getDiscoveraddress().trim();
						String event9xlsSourceAddress = event9xls.getSourceaddress().trim();
//						(1) 待入库的事件有来源地址
						if(!event9xlsSourceAddress.equals("")) {
//							有来源地址
							if(eventsourceaddressName.equals(event9xlsSourceAddress)) {
								return foodByName;
							}
//						(2) 待入库的事件没有发现地址
						}else {
//							（2.1）待入库的事件有发现地址
							if(!event9xlsDiscoveryAddress.equals("")) {
								if(eventdiscoveryaddressName.equals(event9xlsDiscoveryAddress)) {
									return foodByName;
								}
//							（2.2）待入库的事件没有发现地址
							}else {
								if(event.getDiscoveryAddress().getId() == -2) {
									return foodByName;
								}
							}
						}
					}					
				}
			}		
		}
	
//		没有还没有返回，表示没有找到食物，新建一个食物
		Food food = entityFactory.initFood();
		food.setName(foodName);
		food = foodService.saveFood(food);

		return food;
	}

// 获取精确的类型，如果没有找到就使用著类型，如果都为空，就返回-2的那个类型
	private Foodtype buildFoodtype(Event9ld enent9zwz) {
		
		Foodtype foodtype = CmiSetUtil.getSoleInstance(foodtypeDAO.findFoodtypeByName(enent9zwz.getFoodtype()));
		if(foodtype == null) {
			foodtype = foodtypeDAO.findFoodtypeById(-2);
		}
		return foodtype;
	}

}